package com.wande.dataplatform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.wande.common.core.exception.ServiceException;
import com.wande.dataplatform.domain.AssetCategory;
import com.wande.dataplatform.domain.DataAsset;
import com.wande.dataplatform.domain.dto.AssetCategoryDTO;
import com.wande.dataplatform.mapper.AssetCategoryMapper;
import com.wande.dataplatform.mapper.DataAssetMapper;
import com.wande.dataplatform.service.IAssetCategoryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 资产分类Service业务层处理
 *
 * @author ruoyi
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class AssetCategoryServiceImpl implements IAssetCategoryService {

    private final AssetCategoryMapper baseMapper;
    private final DataAssetMapper assetMapper;

    /**
     * 查询资产分类
     */
    @Override
    public AssetCategoryDTO queryById(Long id) {
        AssetCategory category = baseMapper.selectById(id);
        if (category == null) {
            throw new ServiceException("资产分类不存在");
        }
        AssetCategoryDTO dto = BeanUtil.copyProperties(category, AssetCategoryDTO.class);
        
        // 统计该分类下的资产数量
        Long count = assetMapper.selectCount(
            Wrappers.lambdaQuery(DataAsset.class)
                .eq(DataAsset::getCategoryId, id)
        );
        dto.setAssetCount(Math.toIntExact(count));
        
        return dto;
    }

    /**
     * 查询资产分类列表
     */
    @Override
    public List<AssetCategoryDTO> queryList(AssetCategoryDTO dto) {
        LambdaQueryWrapper<AssetCategory> lqw = buildQueryWrapper(dto);
        List<AssetCategory> list = baseMapper.selectList(lqw);
        
        return list.stream()
            .map(category -> {
                AssetCategoryDTO categoryDTO = BeanUtil.copyProperties(category, AssetCategoryDTO.class);
                // 统计该分类下的资产数量
                Long count = assetMapper.selectCount(
                    Wrappers.lambdaQuery(DataAsset.class)
                        .eq(DataAsset::getCategoryId, category.getId())
                );
                categoryDTO.setAssetCount(Math.toIntExact(count));
                return categoryDTO;
            })
            .collect(Collectors.toList());
    }

    /**
     * 查询资产分类树
     */
    @Override
    public List<AssetCategoryDTO> queryTree(Long projectId) {
        LambdaQueryWrapper<AssetCategory> lqw = Wrappers.lambdaQuery();
        if (projectId != null) {
            lqw.eq(AssetCategory::getProjectId, projectId);
        }
        lqw.eq(AssetCategory::getStatus, 1);
        lqw.orderByAsc(AssetCategory::getSortOrder);
        
        List<AssetCategory> allCategories = baseMapper.selectList(lqw);
        
        // 转换为DTO并统计资产数量
        List<AssetCategoryDTO> allDtos = allCategories.stream()
            .map(category -> {
                AssetCategoryDTO dto = BeanUtil.copyProperties(category, AssetCategoryDTO.class);
                // 统计该分类下的资产数量
                Long count = assetMapper.selectCount(
                    Wrappers.lambdaQuery(DataAsset.class)
                        .eq(DataAsset::getCategoryId, category.getId())
                );
                dto.setAssetCount(Math.toIntExact(count));
                return dto;
            })
            .collect(Collectors.toList());
        
        // 构建树形结构
        return buildTree(allDtos, 0L);
    }

    /**
     * 构建树形结构
     */
    private List<AssetCategoryDTO> buildTree(List<AssetCategoryDTO> allCategories, Long parentId) {
        List<AssetCategoryDTO> tree = new ArrayList<>();
        
        for (AssetCategoryDTO category : allCategories) {
            if (parentId.equals(category.getParentId())) {
                List<AssetCategoryDTO> children = buildTree(allCategories, category.getId());
                category.setChildren(children);
                tree.add(category);
            }
        }
        
        return tree;
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<AssetCategory> buildQueryWrapper(AssetCategoryDTO dto) {
        LambdaQueryWrapper<AssetCategory> lqw = Wrappers.lambdaQuery();
        lqw.like(StrUtil.isNotBlank(dto.getName()), AssetCategory::getName, dto.getName());
        lqw.eq(StrUtil.isNotBlank(dto.getCode()), AssetCategory::getCode, dto.getCode());
        lqw.eq(dto.getParentId() != null, AssetCategory::getParentId, dto.getParentId());
        lqw.eq(dto.getStatus() != null, AssetCategory::getStatus, dto.getStatus());
        lqw.eq(dto.getProjectId() != null, AssetCategory::getProjectId, dto.getProjectId());
        lqw.orderByAsc(AssetCategory::getSortOrder);
        return lqw;
    }

    /**
     * 新增资产分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insertCategory(AssetCategoryDTO dto) {
        AssetCategory category = BeanUtil.copyProperties(dto, AssetCategory.class);
        
        // 设置层级
        if (category.getParentId() != null && category.getParentId() > 0) {
            AssetCategory parent = baseMapper.selectById(category.getParentId());
            if (parent != null) {
                category.setLevel(parent.getLevel() + 1);
            }
        } else {
            category.setParentId(0L);
            category.setLevel(1);
        }
        
        // 默认状态为启用
        if (category.getStatus() == null) {
            category.setStatus(1);
        }
        
        baseMapper.insert(category);
        return category.getId();
    }

    /**
     * 修改资产分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateCategory(AssetCategoryDTO dto) {
        AssetCategory category = baseMapper.selectById(dto.getId());
        if (category == null) {
            throw new ServiceException("资产分类不存在");
        }
        
        BeanUtil.copyProperties(dto, category, "id", "createTime");
        
        // 更新层级
        if (category.getParentId() != null && category.getParentId() > 0) {
            AssetCategory parent = baseMapper.selectById(category.getParentId());
            if (parent != null) {
                category.setLevel(parent.getLevel() + 1);
            }
        } else {
            category.setParentId(0L);
            category.setLevel(1);
        }
        
        return baseMapper.updateById(category) > 0;
    }

    /**
     * 批量删除资产分类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteByIds(List<Long> ids) {
        // 检查是否有子分类
        for (Long id : ids) {
            Long count = baseMapper.selectCount(
                Wrappers.lambdaQuery(AssetCategory.class)
                    .eq(AssetCategory::getParentId, id)
            );
            if (count > 0) {
                throw new ServiceException("存在子分类，无法删除");
            }
            
            // 检查是否有关联的资产
            Long assetCount = assetMapper.selectCount(
                Wrappers.lambdaQuery(DataAsset.class)
                    .eq(DataAsset::getCategoryId, id)
            );
            if (assetCount > 0) {
                throw new ServiceException("该分类下存在资产，无法删除");
            }
        }
        
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 删除资产分类信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        // 检查是否有子分类
        Long count = baseMapper.selectCount(
            Wrappers.lambdaQuery(AssetCategory.class)
                .eq(AssetCategory::getParentId, id)
        );
        if (count > 0) {
            throw new ServiceException("存在子分类，无法删除");
        }
        
        // 检查是否有关联的资产
        Long assetCount = assetMapper.selectCount(
            Wrappers.lambdaQuery(DataAsset.class)
                .eq(DataAsset::getCategoryId, id)
        );
        if (assetCount > 0) {
            throw new ServiceException("该分类下存在资产，无法删除");
        }
        
        return baseMapper.deleteById(id) > 0;
    }

}
